package com.ff.xyh.api.minio.controller;

import com.ff.xyh.common.entity.result.ResultMessage;
import com.ff.xyh.common.utils.MinioUtils;
import com.ff.xyh.common.entity.result.ResultObject;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;

/**
 * @Auther FF
 * @Date 2022年 10月 24日
 * @Time 13:12
 */
@Slf4j
@RestController
@RequestMapping(value = "/minio")
public class MinioController {

    @Autowired
    private MinioClient minioClient;

    @Value("${minio.bucketname}")
    private String bucketName;

    /**
     * 获取指定目录文件列表
     */
    @GetMapping("get-filelist")
    public ResultObject getAllFileList(String dir) throws Exception {
        List<Object> list = MinioUtils.getFiles(minioClient, bucketName, dir);
        Map map = new HashMap<>();
        map.put("items", list);
        return ResultObject.ok().data(map);
    }

    /**
     * 删除指定目录下的文件
     * @param dir
     * @return
     */
    @PostMapping("delete-dir")
    public ResultObject deleteFilesInDir(
            @RequestParam(name = "dir", required = false) String dir) {
        if (StringUtils.isEmpty(dir) || dir.contains("."))
            return ResultObject.error().message("上传路径有误");
        try {
            List<Object> list = MinioUtils.deleteDir(minioClient, bucketName, dir);
            Map map = new HashMap<>();
            map.put("items", list);
            return ResultObject.ok().data(map);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultObject.error().message(ResultMessage.FAILED_TO_DELETE);
        }
    }

    @PostMapping("delete-file")
    public ResultObject deleteFile(@RequestParam(name = "objectName") String objectName) {
        try {
            if (MinioUtils.deleteObject(minioClient, bucketName, objectName))
                return ResultObject.ok().message("删除成功");
            else
                return ResultObject.error().message("删除失败");
        } catch (Exception e) {
            e.printStackTrace();
            return ResultObject.error().message("删除出错");
        }
    }

    @GetMapping("download-file")
    public void downloadFileInDir(
            String objectName,
            HttpServletResponse response) {
        InputStream in = null;
        try {
            StatObjectResponse statObjectResponse = MinioUtils.getStatObjectResponse(minioClient, bucketName, objectName);
            response.setContentType(statObjectResponse.contentType());
            response.setHeader("Content-Disposition", "attachment;filename=" +
                    URLEncoder.encode(objectName.substring(
                            objectName.lastIndexOf('/'), objectName.length()
                            ), "UTF-8")
            );
            in = MinioUtils.downloadFile(minioClient, bucketName, objectName);
            // 复制输入流到响应体输出流就能给前端用户了
            IOUtils.copy(in, response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

//    @PostMapping("upload-files")
//    public ResultObject uploadFiles(
//            @RequestBody MultipartFile[] files,
//            @RequestParam(name = "path") String path) {
//        if (files == null || files.length == 0) {
//            return ResultObject.error().message("上传文件不能为空");
//        }
//        // path /files/(shop/travel)/uuid/
//        List<String> filePathList = new ArrayList<>(files.length);
//        List<String> failedUploadPathList = new ArrayList<>();
//        int failedCount = 0;
//        for (MultipartFile file : files) {
//            String originalFileName = path + file.getOriginalFilename();
//            if (!MinioUtils.uploadFile(minioClient, bucketName, path, file)){
//                failedUploadPathList.add(originalFileName);
//                failedCount++;
//                continue;
//            }
//            filePathList.add((path + originalFileName));
//        }
//        Map map = new HashMap();
//        // 上传时发送错误
//        if (failedCount > 0) {
//            map.put("failedItems", failedUploadPathList);
//            map.put("items", filePathList);
//            return ResultObject.error().data(map)
//                    .message(failedCount + "个文件上传失败，部分文件上传成功， 保存路径为: " + bucketName + path);
//        } else {
//            // 没有发生错误
//            map.put("path", bucketName + path);
//            map.put("items", filePathList);
//            return ResultObject.ok().data(map)
//                    .message("文件集上传成功， 保存路径为: " + bucketName + path);
//        }
//    }

    /**
     * 上传多个文件到指定的随机路径 并按顺序命名
     * @param files
     * @param path /img-files/(shop/travel)/uuid/
     * @return
     */
    @PostMapping("upload-files")
    public ResultObject uploadFiles(
            @RequestParam(name = "files") MultipartFile[] files,
            @RequestParam(name = "path") String path) {
        System.out.println(files[0].getOriginalFilename());
        if (files == null || files.length == 0) {
            return ResultObject.error().message("上传文件不能为空");
        }
        // path /img-files/(shop/travel)/uuid/
        List<String> filePathList = new ArrayList<>(files.length);
        List<String> failedUploadPathList = new ArrayList<>();
        int failedCount = 0;
        for (int i = 0; i < files.length; i++) {
            String originalFilename = files[i].getOriginalFilename();
            String saveFilename = i + MinioUtils.getFileSuffix(originalFilename);
            // saveFilename: /files/(shop/travel)/uuid/  saveFilename: i.png
            if (! MinioUtils.uploadFile(
                    minioClient, bucketName, path, files[i], saveFilename)) {
                failedUploadPathList.add(path + originalFilename);
                failedCount++;
                continue;
            }
            filePathList.add((path + saveFilename));
        }
        Map map = new HashMap();
        // 上传时发送错误
        if (filePathList.isEmpty()) {
            map.put("failedItems", failedUploadPathList);
            map.put("items", filePathList);
            return ResultObject.error().data(map)
                    .message(failedCount + "个文件上传失败，部分文件上传成功， 保存路径为: " + bucketName + path);
        } else {
            // 没有发生错误
            map.put("path", bucketName + path);
            map.put("items", filePathList);
            return ResultObject.ok().data(map)
                    .message("文件集上传成功， 保存路径为: " + bucketName + path);
        }
    }

    /**
     * 上传单个文件到指定文件位置
     * @param file
     * @param pathAndFilename /img-files/(shop/travel)/uuid/xxxx.png
     * @return
     */
    @PostMapping(value = "upload-file-path", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ResultObject uploadFileToPath(
            @RequestParam(name = "file") MultipartFile file,
            @RequestParam(name = "pathAndFilename") String pathAndFilename) {
        if (file == null) {
            return ResultObject.error().message("上传文件不能为空");
        }
        // pathAndFilename /(shop/travel)/uuid/xxxx.png
        if (!MinioUtils.uploadFile(
                minioClient, bucketName, pathAndFilename, file))
            return ResultObject.error().message("上传" + file.getOriginalFilename() + "出错啦");

        return ResultObject.ok()
                .data("data", bucketName + pathAndFilename)
                .message("上传成功， 保存路径为: " + bucketName + pathAndFilename);

    }
//    @PostMapping("upload-files")
//    public ResultObject uploadFiles(
//            @RequestBody MultipartFile[] files) {
//        if (files == null || files.length == 0) {
//            return ResultObject.error().message("上传文件不能为空");
//        }
//        // 可以先经过微服务接口将传入情景参数写入redis在来读取
//        String path = "/test/files/";
//        List<String> filePathList = new ArrayList<>(files.length);
//        List<String> falseFilePathList = new ArrayList<>();
//        int falseCount = 0;
//        for (MultipartFile file : files) {
//            String originalFileName = path + file.getOriginalFilename();
//            if (!MinioUtils.uploadFile(minioClient, bucketName, path, file)){
//                falseFilePathList.add((path + originalFileName));
//                falseCount++;
//                continue;
//            }
//            filePathList.add((path + originalFileName));
//        }
//        Map map = new HashMap();
//        // 上传时发送错误
//        if (falseCount > 0) {
//            map.put("falseItems", falseFilePathList);
//            map.put("items", filePathList);
//            return ResultObject.error().data(map)
//                    .message("部分文件上传失败，部分文件上传成功， 保存路径为: " + bucketName + path);
//        } else {
//            // 没有发生错误
//            map.put("items", filePathList);
//            return ResultObject.ok().data(map)
//                    .message("文件集上传成功， 保存路径为: " + bucketName + path);
//        }
//    }

    /**
     * 上传单个文件
     * @param file
     * @return
     */
    @PostMapping("upload-file")
    public ResultObject uploadFile(
            @RequestBody MultipartFile file) {
        if (file == null) {
            return ResultObject.error().message("上传文件不能为空");
        }
        String path = "/test/files/";
        if (!MinioUtils.uploadFile(minioClient, bucketName, path, file))
            return ResultObject.error().message("上传" + file.getOriginalFilename() + "出错啦");

        return ResultObject.ok().message("上传成功， 保存路径为: " + bucketName + path + file.getOriginalFilename());
    }



    /**
     * 头像上传
     * @param file
     * @param uuid 临时生成uuid
     * @return
     */
    @PostMapping("upload-avatar")
    public ResultObject uploadAvatar(
            @RequestParam(name = "file", required = false) MultipartFile file,
            @RequestParam(name = "uuid", required = false) String uuid) {
        if (file == null)
            return ResultObject.error().message("上传文件不能为空");
        else if ( StringUtils.isEmpty(uuid))
            return ResultObject.error().message("没有指定上传用户id");
        else if ( ! file.getContentType().contains("image"))
            return ResultObject.error().message("上传的文件不是图片类型");

        String path = "/img-files/avatar/%s/";
        path = String.format(path, uuid);
        System.out.println(file.getContentType());
        if (!MinioUtils.uploadFile(
                minioClient, bucketName, path, file,
                uuid+MinioUtils.getFileSuffix(file.getOriginalFilename())))
            return ResultObject.error().message("上传头像出错啦");
        else {
            Map map = new HashMap();
            map.put("uuid", uuid);
            map.put("data", bucketName + path + uuid + MinioUtils.getFileSuffix(file.getOriginalFilename()));
            return ResultObject.ok().data(map);
        }
     }

    /**
     * 帖子照片集上传
     * @param files
     * @param id 帖子id
     * @param postType 帖子类型
     * @return
     */
    @PostMapping("upload-files-post-imgs")
    public ResultObject uploadFilesPostImgs(
            @RequestBody(required = false) MultipartFile[] files,
            @RequestParam(name = "id", required = false) String id,
            @RequestParam(name = "postType", required = false) String postType) {
        if (files == null || files.length == 0)
            return ResultObject.error().message("上传文件不能为空");
        else if (files.length > 9)
            return ResultObject.error().message("上传文件超过9个");
        else if (StringUtils.isEmpty(id))
            return ResultObject.error().message("未指定帖子id");
        // 可以先经过微服务接口将传入情景参数写入redis在来读取
        String path = "/img-files/post/%s/%s/";
        path = String.format(path, postType, id);
        List<String> filePathList = new ArrayList<>(files.length);

        for (MultipartFile file : files) {
            String originalFileName = path + file.getOriginalFilename();
            if (!MinioUtils.uploadFile(minioClient, bucketName, path, file)){
                return ResultObject.error().message(
                        "上传" + originalFileName + "出错啦 但"
                                + filePathList + " 文件已被上传");
            }
            filePathList.add(originalFileName);
        }
        Map map = new HashMap();
        map.put("items", filePathList);
        return ResultObject.ok().data(map)
                .message("帖子照片集上传成功， 保存路径为: " + bucketName + path);
    }

}
